package com.asdhawaii.ics111game.room;

import com.asdhawaii.ics111game.item.Item;
import com.asdhawaii.ics111game.person.Person;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;

/**
 * Tests the Room class.
 * 
 * @author Branden Ogata
 *
 */

public class TestRoom
{
  /**
   * Tests the methods in the Room class.
   * 
   */
  
  @Test
  public void test()
  {
    // Room instances for testing
    Room alphaRoom = new Room("Bedroom for Alpha", "A spacious bedroom where Alpha sleeps.", 
                              "The room is sparsely decorated, but what ornementation exists " +
                              "does give the room a distinctly feminine touch.");
    Room betaRoom = new Room("Bedroom for Beta", "A spacious bedroom where Beta sleeps.", 
                             "The room is brightly colored, and you feel more energetic just " + 
                             "from entering.");
    Room gammaRoom = new Room("Bedroom for Gamma", "A spacious bedroom where Gamma sleeps.",
                              "The room is quite austere and utilitarian.  The only indication " +
                              "that the room is in fact inhabited is the brown teddy bear " + 
                              "propped up against the pillow on the bed.");
    
    // Test accessor methods
    assertEquals("Check getName", alphaRoom.getName(), "Bedroom for Alpha");
    assertEquals("Check getShortDescription", betaRoom.getShortDescription(), 
                 "A spacious bedroom where Beta sleeps.");
    assertEquals("Check getLongDescription", gammaRoom.getLongDescription(), 
                 "The room is quite austere and utilitarian.  The only indication " +
                 "that the room is in fact inhabited is the brown teddy bear " + 
                 "propped up against the pillow on the bed.");
    
    // Test interaction with Item instances
    Item bear = new Item("teddy bear", "A small stuffed animal.", "The stuffed bear shows signs " +
                         "of considerable wear over the years; certainly it appears older than " +
                         "Gamma herself.", false, false, true, 10.24, 4.0, 400.0, false);
    Item book = new Item("book", "A thin novel that Alpha is slowly reading through.",
                         "Based on the placement of the bookmark, you estimate that Alpha is " + 
                         "roughly a third done with the book.  The book seems to be a work of " +
                         "historical fiction covering the time period of the American Civil War.", 
                         false, false, true, 19.99, 2.0, 100.0, false);
    Item piggyBank = new Item("piggy bank", "A ceramic piggy bank.", "Beta stores much of her " +
                              "wages inside this piggy bank.", false, false, true, 5.00, 3.0, 100.0,
                              false);
    Item pen = new Item("pen", "A writing implement.", "This strange device places ink onto paper.",
                        false, false, true, 1.50, 0.5, 2.0, false);
    alphaRoom.addItem(book);
    betaRoom.addItem(piggyBank);
    gammaRoom.addItem(bear);
    alphaRoom.addItem(pen);
    betaRoom.addItem(pen);
    gammaRoom.addItem(pen);
    assertTrue("Check contents of alphaRoom", alphaRoom.getContents().contains(book) &&
                                              alphaRoom.getContents().contains(pen));
    assertTrue("Check contents of betaRoom", betaRoom.getContents().contains(piggyBank) &&
                                             betaRoom.getContents().contains(pen));
    assertTrue("Check contents of gammaRoom", gammaRoom.getContents().contains(bear) &&
                                              gammaRoom.getContents().contains(pen));
    // Remove book and pen from alphaRoom to place into betaRoom
    // (since betaRoom already has a pen, the non-unique pen from alphaRoom is not added)
    // and remove pen from gammaRoom
    List<Item> tempItems = alphaRoom.removeAllItems();
    for (Item i : tempItems)
    {
      betaRoom.addItem(i);
    }
    gammaRoom.removeItem("pen");
    assertTrue("Check contents of alphaRoom after removeAll", alphaRoom.getContents().isEmpty());
    assertTrue("Check contents of betaRoom after moving Alpha items",
               betaRoom.getContents().size() == 3 && 
               betaRoom.getContents().get(0).equals(book) && 
               betaRoom.getContents().get(1).equals(pen) &&
               betaRoom.getContents().get(2).equals(piggyBank));
    assertTrue("Check contents of gammaRoom after removing", 
               gammaRoom.getContents().size() == 1 && 
               gammaRoom.getContents().get(0).equals(bear));   
    
    // Test interaction with Person instances
    Person alpha = new Person("Alpha", "A young girl.", "The prototypical protagonist.");
    Person beta = new Person("Beta", "A female child.", "An energetic girl.");
    Person gamma = new Person("Gamma", "A calm, composed lady.", "Reserved and elegant.");
    alphaRoom.addPerson(alpha);
    betaRoom.addPerson(beta);
    gammaRoom.addPerson(gamma);
    assertTrue("Check people in alphaRoom", alphaRoom.getPeople().contains(alpha));
    assertTrue("Check people in betaRoom", betaRoom.getPeople().contains(beta));
    assertTrue("Check people in gammaRoom", gammaRoom.getPeople().contains(gamma));
    // Alpha and Beta move to gammaRoom
    alphaRoom.move("alpha", gammaRoom);
    betaRoom.move("beta", gammaRoom);
    assertTrue("Check that all three are in gammaRoom", 
               gammaRoom.getPeople().size() == 3 && 
               gammaRoom.getPeople().get(0).equals(alpha) &&
               gammaRoom.getPeople().get(1).equals(beta) &&
               gammaRoom.getPeople().get(2).equals(gamma) &&
               alphaRoom.getPeople().isEmpty() && 
               betaRoom.getPeople().isEmpty());
    
    // Test movement
    // Rooms
    Room center = new Room("Center", "The center room.", 
                           "A hub from which the occupant may go in any direction.");
    Room north = new Room("North", "The north room.", 
                          "A room to the north of center.");
    Room northeast = new Room("Northeast", "The northeast room.", 
                              "A room to the northeast of center.");
    Room east = new Room("East", "The east room.", 
                         "A room to the east of center.");
    Room southeast = new Room("Southeast", "The southeast room.", 
                              "A room to the southeast of center.");
    Room south = new Room("South", "The south room.", 
                          "A room to the south of center.");
    Room southwest = new Room("Southwest", "The southwest room.", 
                              "A room to the southwest of center.");
    Room west = new Room("West", "The west room.", 
                         "A room to the west of center.");
    Room northwest = new Room("Northwest", "The northwest room.", 
                              "A room to the northwest of center.");
    Room up = new Room("Up", "The above room.", 
                       "A room above center.");
    Room down = new Room("Down", "The below room.", 
                         "A room below center.");
    
    // Create connections between rooms
    // Center
    center.setNorth(north);
    center.setNortheast(northeast);
    center.setEast(east);
    center.setSoutheast(southeast);
    center.setSouth(south);
    center.setSouthwest(southwest);
    center.setWest(west);
    center.setNorthwest(northwest);
    center.setUp(up);
    center.setDown(down);
    
    // North
    north.setEast(northeast);
    north.setSoutheast(east);
    north.setSouth(center);
    north.setSouthwest(west);
    north.setWest(northwest);
    
    // Northeast
    northeast.setSouth(east);
    northeast.setSouthwest(center);
    northeast.setWest(north);
    
    // East
    east.setNorth(northeast);
    east.setSouth(southeast);
    east.setSouthwest(south);
    east.setWest(center);
    east.setNorthwest(north);
    
    // Southeast
    southeast.setNorth(east);
    southeast.setWest(south);
    southeast.setNorthwest(center);
    
    // South
    south.setNorth(center);
    south.setNortheast(east);
    south.setEast(southeast);
    south.setWest(southwest);
    south.setNorthwest(west);
    
    // Southwest
    southwest.setNorth(west);
    southwest.setNortheast(center);
    southwest.setEast(south);
    
    // West
    west.setNorth(northwest);
    west.setNortheast(north);
    west.setEast(center);
    west.setSoutheast(south);
    west.setSouth(southwest);
    
    // Northwest
    northwest.setEast(north);
    northwest.setSoutheast(center);
    northwest.setSouth(west);
    
    // Up
    up.setDown(center);
    
    // Down
    down.setUp(center);
    
    // Simple Test:
    // Verify that connections between rooms exist where they should,
    // and that there are no unintended connections
    assertTrue("Check center: north", center.getNorth().equals(north));
    assertTrue("Check center: northeast", center.getNortheast().equals(northeast));
    assertTrue("Check center: east", center.getEast().equals(east));
    assertTrue("Check center: southeast", center.getSoutheast().equals(southeast));
    assertTrue("Check center: south", center.getSouth().equals(south));
    assertTrue("Check center: southwest", center.getSouthwest().equals(southwest));
    assertTrue("Check center: west", center.getWest().equals(west));
    assertTrue("Check center: northwest", center.getNorthwest().equals(northwest));
    assertTrue("Check center: up", center.getUp().equals(up));
    assertTrue("Check center: down", center.getDown().equals(down));
    assertTrue("Check up: north", up.getNorth() == null);
    assertTrue("Check up: northeast", up.getNortheast() == null);
    assertTrue("Check up: east", up.getEast() == null);
    assertTrue("Check up: southeast", up.getSoutheast() == null);
    assertTrue("Check up: south", up.getSouth() == null);
    assertTrue("Check up: southwest", up.getSouthwest() == null);
    assertTrue("Check up: west", up.getWest() == null);
    assertTrue("Check up: northwest", up.getNorthwest() == null);
    assertTrue("Check up: up", up.getUp() == null);
    assertTrue("Check up: down", up.getDown().equals(center));
    
    // Place Alpha, Beta, and Gamma inside to navigate
    // Alpha goes up and down from center, then explores the diagonals before returning to center
    center.addPerson(alpha);
    alphaRoom = center;
    alphaRoom.move("alpha", alphaRoom = alphaRoom.getExit(Direction.UP));
    alphaRoom.move("alpha", alphaRoom = alphaRoom.getExit(Direction.DOWN));
    alphaRoom.move("alpha", alphaRoom = alphaRoom.getExit(Direction.DOWN));
    alphaRoom.move("alpha", alphaRoom = alphaRoom.getExit(Direction.UP));
    // Back at center
    alphaRoom.move("alpha", alphaRoom = alphaRoom.getExit(Direction.NORTHWEST));
    alphaRoom.move("alpha", alphaRoom = alphaRoom.getExit(Direction.SOUTHEAST));
    alphaRoom.move("alpha", alphaRoom = alphaRoom.getExit(Direction.SOUTHEAST));
    alphaRoom.move("alpha", alphaRoom = alphaRoom.getExit(Direction.NORTHWEST));
    // Back at center
    alphaRoom.move("alpha", alphaRoom = alphaRoom.getExit(Direction.NORTHEAST));
    alphaRoom.move("alpha", alphaRoom = alphaRoom.getExit(Direction.SOUTHWEST));
    alphaRoom.move("alpha", alphaRoom = alphaRoom.getExit(Direction.SOUTHWEST));
    alphaRoom.move("alpha", alphaRoom = alphaRoom.getExit(Direction.NORTHEAST));
    // Back at center; stop here
    
    // Beta does a loop around before returning to center
    center.addPerson(beta);
    betaRoom = center;
    betaRoom.move("beta", betaRoom = betaRoom.getExit(Direction.NORTH));
    betaRoom.move("beta", betaRoom = betaRoom.getExit(Direction.EAST));
    betaRoom.move("beta", betaRoom = betaRoom.getExit(Direction.SOUTH));
    betaRoom.move("beta", betaRoom = betaRoom.getExit(Direction.SOUTH));
    betaRoom.move("beta", betaRoom = betaRoom.getExit(Direction.WEST));
    betaRoom.move("beta", betaRoom = betaRoom.getExit(Direction.WEST));
    betaRoom.move("beta", betaRoom = betaRoom.getExit(Direction.NORTH));
    betaRoom.move("beta", betaRoom = betaRoom.getExit(Direction.NORTH));
    betaRoom.move("beta", betaRoom = betaRoom.getExit(Direction.SOUTHEAST));
    // Back at center; stop here
    
    // Gamma does a series of vertical, then horizontal sweeps before returning to center
    center.addPerson(gamma);
    gammaRoom = center;
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.NORTHWEST));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.SOUTH));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.SOUTH));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.EAST));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.NORTH));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.NORTH));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.EAST));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.SOUTH));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.SOUTH));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.NORTHWEST));
    // Back at center
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.NORTHWEST));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.EAST));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.EAST));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.SOUTH));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.WEST));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.WEST));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.SOUTH));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.EAST));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.EAST));
    gammaRoom.move("gamma", gammaRoom = gammaRoom.getExit(Direction.NORTHWEST));
    // Back at center; stop here
    
    // Move all three to the upper room
    alphaRoom.move("alpha", alphaRoom.getExit(Direction.UP));
    betaRoom.move("beta", betaRoom.getExit(Direction.UP));
    gammaRoom.move("gamma", gammaRoom.getExit(Direction.UP));
    
    // Check that all three are in the upper room
    assertTrue("Check movement", up.getPeople().get(0).equals(alpha) &&
                                 up.getPeople().get(1).equals(beta) &&
                                 up.getPeople().get(2).equals(gamma)); 
  }
}
